﻿using System;
using System.Collections;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Web;

namespace Framework
{
    /// <summary>
    /// 文件上传帮助
    /// </summary>
    public class UploadHelper
    {
        public enum UploadFileTypeEnum
        {
            File = 1,
            Image = 2,
            Media = 3,
            Flash = 4,
            Offic = 5
        }

        public UploadHelper(HttpPostedFileBase postedFile, string relativePath)
        {
            PostedFile = postedFile;
            RelativePath = relativePath;
            ThumbnailHeight = 200;
            ThumbnailWidth = 200;
            RelativePath = "~/Upload/";
            IsImage = false;
            IsAdaptive = true;
            IsGenerateThumbnail = true;
            ThumbnailPrefix = "thum";
            FileMaxLength = 1024 * 1024 * 2;
            NormalHeight = 400;
            NormalWidth = 400;
            NormalPrefix = "normal";
            IsGenerateNormal = false;
            NormalModel = 1;
            IsDefaultCheckFileType = true;
        }
        public UploadHelper()
        {
            ThumbnailHeight = 200;
            ThumbnailWidth = 200;
            RelativePath = "~/Upload/";
            IsImage = false;
            IsAdaptive = true;
            IsGenerateThumbnail = true;
            ThumbnailPrefix = "thum";
            FileMaxLength = 1024 * 1024 * 2;
            NormalHeight = 400;
            NormalWidth = 400;
            NormalPrefix = "normal";
            IsGenerateNormal = false;
            NormalModel = 1;
            IsDefaultCheckFileType = true;
        }
        public bool IsWaterMark { get; set; }
        public string WaterMarkRelativePath { get; set; }
        public string WaterMarkFileName { get; set; }
        public string WaterMarkFileRelativePath { get { return Path.Combine(WaterMarkRelativePath, WaterMarkFileName); } }
        public string WaterMarkFilePhyPath { get; set; }
        /// <summary>
        /// 文件类型，用于自定义匹配
        /// </summary>
        public string FileType { get; set; }
        /// <summary>
        /// 默认检查文件匹配
        /// </summary>
        public UploadFileTypeEnum UploadFileType { get; set; }
        /// <summary>
        /// 是否按默认格式检查文件
        /// </summary>
        public bool IsDefaultCheckFileType { get; set; }
        /// <summary>
        /// PostedFile数据
        /// </summary>
        public HttpPostedFileBase PostedFile { get; set; }
        /// <summary>
        /// 原文件名
        /// </summary>
        public string OriginalFileName { get; set; }
        /// <summary>
        /// 文件名
        /// </summary>
        public string FileName { get; set; }
        /// <summary>
        /// 相对目录路径
        /// </summary>
        public string RelativePath { get; set; }
        /// <summary>
        /// 文件扩展名
        /// </summary>
        public string Extension { get; set; }
        /// <summary>
        /// 文件相对路径
        /// </summary>
        public string FileRelativePath { get { return Path.Combine(RelativePath, FileName); } }
        /// <summary>
        /// 文件物理路径
        /// </summary>
        public string FilePhyPath { get { return Path.Combine(PhyPath, FileName); } }
        /// <summary>
        /// 目录物理路径
        /// </summary>
        public string PhyPath { get; private set; }
        /// <summary>
        /// 错误信息
        /// </summary>
        public string ErrorMessage { get; private set; }
        /// <summary>
        /// 文件大小限制
        /// </summary>
        public double FileMaxLength { get; set; }
        /// <summary>
        /// Base64 文件流
        /// </summary>
        public string Base64 { get; set; }
        /// <summary>
        /// 是否是图片
        /// </summary>
        public bool IsImage { get; set; }
        /// <summary>
        /// 是否生成略缩图
        /// </summary>
        public bool IsGenerateThumbnail { get; set; }
        /// <summary>
        /// 是否生成正常图片
        /// </summary>
        public bool IsGenerateNormal { get; set; }
        /// <summary>
        /// 略缩图片文件相对路径
        /// </summary>
        public string ThumbnailFileRelativePath
        {
            get { return Path.Combine(RelativePath, ThumbnailFileName); }
        }
        /// <summary>
        /// 略缩图片文件物理路径
        /// </summary>
        public string ThumbnailFilePhyPath
        {
            get { return Path.Combine(PhyPath, ThumbnailFileName); }
        }
        /// <summary>
        /// 定义允许上传的文件扩展名
        /// </summary>
        public Hashtable ExtTable = new Hashtable
                               {
                                   {UploadFileTypeEnum.Image, "gif,jpg,jpeg,png,bmp"},
                                   {UploadFileTypeEnum.Flash, "swf,flv"},
                                   {UploadFileTypeEnum.Media, "swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb"},
                                   {UploadFileTypeEnum.File, "doc,docx,xls,xlsx,ppt,htm,html,txt,zip,rar,gz,bz2"}
                               };
        /// <summary>
        /// 图片略缩图高
        /// </summary>
        public int ThumbnailHeight { get; set; }
        /// <summary>
        /// 图片略缩图高
        /// </summary>
        public int ThumbnailWidth { get; set; }
        public int NormalHeight { get; set; }
        public int NormalWidth { get; set; }
        public string NormalFileName { get; set; }
        public string NormalPrefix { get; set; }
        /// <summary>
        /// 略缩图片文件相对路径
        /// </summary>
        public string NormalFileRelativePath
        {
            get { return Path.Combine(RelativePath, NormalFileName); }
        }
        /// <summary>
        /// 略缩图片文件物理路径
        /// </summary>
        public string NormalFilePhyPath
        {
            get { return Path.Combine(PhyPath, NormalFileName); }
        }
        /// <summary>
        /// 缩略图片文件名
        /// </summary>
        public string ThumbnailFileName { get; set; }
        /// <summary>
        /// 缩略图片文件名前缀
        /// </summary>
        public string ThumbnailPrefix { get; set; }
        /// <summary>
        ///缩略图片模式
        /// </summary>
        public int ThumbnailModel { get; set; }

        public int NormalModel { get; set; }
        /// <summary>
        /// 缩略图片大小自适应（ThumbnailModel将失效）
        /// </summary>
        public bool IsAdaptive { get; set; }
        /// <summary>
        /// 保存文件
        /// </summary>
        /// <returns></returns>
        public bool Save()
        {
            try
            {
                if (IsImage)
                {
                    UploadFileType = UploadFileTypeEnum.Image;
                }
                if (!CheckFile(UploadFileType)) return false;
                Check.Argument.IsNotNull(PostedFile, "PostedFile");
                Check.Argument.IsNotNull(RelativePath, "RelativePath");
                OriginalFileName = Path.GetFileName(PostedFile.FileName);//获得文件名            
                Extension = Path.GetExtension(PostedFile.FileName);//获得文件扩展名  
                FileName = Guid.NewGuid() + Extension;//实际保存文件名   
                ThumbnailFileName = ThumbnailPrefix + "_" + FileName;
                PhyPath = HttpContext.Current.Server.MapPath(RelativePath);
                NormalFileName = NormalPrefix + "_" + FileName;
                if (!Directory.Exists(PhyPath))
                {
                    Directory.CreateDirectory(PhyPath);
                }
                if (IsImage && IsWaterMark)
                {
                    WaterMarkFilePhyPath = HttpContext.Current.Server.MapPath(WaterMarkFileRelativePath);
                    if (File.Exists(WaterMarkFilePhyPath))
                        ImageExtension.Mark(PostedFile.InputStream, FilePhyPath, WaterMarkFilePhyPath);
                    else
                    {
                        PostedFile.SaveAs(FilePhyPath);
                    }
                }
                else
                {
                    PostedFile.SaveAs(FilePhyPath);
                }
                if (IsImage && IsGenerateThumbnail)
                {
                    if (IsAdaptive)
                    {
                        ImageExtension.ToThumbnail(FilePhyPath, ThumbnailFilePhyPath, ThumbnailHeight, ThumbnailWidth);

                    }
                    else
                    {
                        ImageExtension.ToThumbnail(FilePhyPath, ThumbnailFilePhyPath, ThumbnailHeight, ThumbnailWidth, ThumbnailModel);
                    }
                }
                if (IsImage && IsGenerateNormal)
                {
                    if (IsAdaptive)
                    {
                        ImageExtension.ToThumbnail(FilePhyPath, NormalFilePhyPath, NormalHeight, NormalWidth);

                    }
                    else
                    {
                        ImageExtension.ToThumbnail(FilePhyPath, NormalFilePhyPath, NormalHeight, NormalWidth, NormalModel);
                    }
                }

                return true;
            }
            catch (Exception e)
            {
                throw new ApplicationException(e.Message);
            }

        }
        /// <summary>
        /// 保存文件扩展
        /// </summary>
        /// <param name="postedFile">保存数据</param>
        /// <param name="relativePath">相对目录路径</param>
        /// <returns></returns>
        public bool Save(HttpPostedFileBase postedFile, string relativePath)
        {
            PostedFile = postedFile;
            RelativePath = relativePath;
            return Save();
        }
        /// <summary>
        /// 删除当前文件
        /// </summary>
        /// <returns></returns>
        public bool Delete()
        {
            try
            {
                var phyPath = HttpContext.Current.Server.MapPath(FileRelativePath);
                FileHelper.DeleteSub(phyPath);
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
        /// <summary>
        /// 删除图片
        /// </summary>
        /// <param name="fileRelativePath">文件相对路径</param>
        /// <returns></returns>
        public bool Delete(string fileRelativePath)
        {
            try
            {
                var filePhyPath = HttpContext.Current.Server.MapPath(fileRelativePath);
                FileHelper.DeleteSub(filePhyPath);
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
        /// <summary>
        /// 批量删除图片
        /// </summary>
        /// <param name="fileRelativePath">文件相对路径数组</param>
        /// <returns></returns>
        public bool Delete(string[] fileRelativePath)
        {
            try
            {
                var filePhyPaths = fileRelativePath.Select(o => HttpContext.Current.Server.MapPath(o));
                FileHelper.DeleteSub(filePhyPaths.ToArray());
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// 替换文件
        /// </summary>
        /// <param name="postedFile">post数据</param>

        /// <param name="fileRelativePath">相对路径</param>
        /// <returns></returns>
        public bool ReplaceFile(HttpPostedFileBase postedFile, string fileRelativePath)
        {
            try
            {
                FileName = Path.GetFileName(fileRelativePath);
                Delete();
                RelativePath = Path.GetDirectoryName(fileRelativePath);
                PostedFile = postedFile;
                Save();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
        /// <summary>
        /// 保存文件 
        /// </summary>
        /// <param name="base64"> </param>
        /// <param name="relativepath">相对路径</param>
        /// <returns></returns>
        public bool SaveImage(string base64, string relativepath)
        {
            if (base64 == null)
            {
                return false;
            }
            RelativePath = relativepath;
            FileName = Guid.NewGuid().ToString() + ".jpg";//实际保存文件名   
            try
            {
                byte[] arr = Convert.FromBase64String(base64);
                using (var ms = new MemoryStream(arr))
                {
                    var bmp = new Bitmap(ms);
                    bmp.Save(FilePhyPath, System.Drawing.Imaging.ImageFormat.Jpeg);
                    ms.Close();
                }
                return true;
            }
            catch
            {
                return false;
            }
        }
        /// <summary>
        /// 检查文件
        /// </summary>
        /// <returns></returns>
        public bool CheckFile(UploadFileTypeEnum fileType)
        {
            if (PostedFile != null)
            {
                string ext = (Path.GetExtension(PostedFile.FileName) ?? "").ToLower().Substring(1);

                if (IsDefaultCheckFileType && ExtTable[fileType].SafeToString().Contains(ext))
                {
                }
                else if (!IsDefaultCheckFileType && fileType.SafeToString().Contains(ext))
                {
                }
                else
                {
                    ErrorMessage = "不是有效的格式";
                    if (IsImage)
                        ErrorMessage = "不是有效的图片格式";
                    return false;
                }
                if (PostedFile.ContentLength > FileMaxLength)
                {
                    var contentLength = FileMaxLength;
                    double result;
                    string lblUnit;
                    if (contentLength >= 1073741824)
                    {
                        result = contentLength / 1073741824.00F;
                        lblUnit = "GB";
                    }
                    else if (contentLength >= 1048576)
                    {
                        result = contentLength / 1048576.00F;
                        lblUnit = "MB";
                    }
                    else
                    {
                        result = contentLength / 1024.00F;
                        lblUnit = "KB";
                    }
                    ErrorMessage = "文件大小不能超过" + result + lblUnit + "!";
                    if (IsImage)
                        ErrorMessage = "图像大小不能超过" + result + lblUnit;
                    return false;
                }
            }
            return true;
        }
    }
}
